package se.djupfeldt.oscar.logbook.console;

import java.io.Console;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;

import org.apache.log4j.Logger;

import se.djupfeldt.oscar.logbook.console.commands.Command;
import se.djupfeldt.oscar.logbook.console.commands.Exit;
import se.djupfeldt.oscar.logbook.console.commands.Help;
import se.djupfeldt.oscar.logbook.console.commands.Position;
import se.djupfeldt.oscar.logbook.console.commands.Select;

public class ConsoleHandler {
    private static ConsoleHandler instance;
    private boolean running;
    
    private HashMap<String, Command> commands;
    
    private ConsoleHandler() {
	commands = new HashMap<String, Command>();
    }
    
    public static ConsoleHandler getInstance() {
	if (instance == null)
	    instance = new ConsoleHandler();
	return instance;
    }
    
    public void initCommands() {
	commands.put(Help.class.getSimpleName().toLowerCase(), Help.getInstance());
	commands.put(Exit.class.getSimpleName().toLowerCase(), Exit.getInstance());
	commands.put("quit", Exit.getInstance());
	commands.put("select", Select.getInstance());
	commands.put("position", Position.getInstance());
    }
    
    public void start() {
	new Thread("Console") {
	    @Override
	    public void run() {
		Console console = System.console();
		boolean consoleAvailable = (console != null);
		Logger.getLogger(getClass()).info("Console method: " + (consoleAvailable ? "Console" : "Scanner") + " (" + consoleAvailable + ")");
		running = true;
		
		while (running) {
		    String cmd;
		    if (consoleAvailable) {
			cmd = console.readLine("> ").toLowerCase();
		    } else {
			Scanner scanner = new Scanner(System.in);
			System.out.print("> ");
			cmd = scanner.nextLine().toLowerCase();
		    }
		    
		    if (cmd == null || cmd.isEmpty()) {
			continue;
		    }
		    
		    String[] args = getArgs(cmd);
		    Command command = parseCommand(cmd);
		    
		    if (command == null) {
			if (consoleAvailable) {
			    console.printf("", "Unknown command: " + cmd);
			} else {
			    System.out.println("Unknown command: " + cmd);
			}
		    }

		    String result = command.execute(args);
		    if (result != null && !result.isEmpty()) {
			if (consoleAvailable) {
			    console.printf("", result);
			} else {
			    System.out.println(result);
			}
		    }
		}
	    }
	}.start();
    }
    
    protected Command parseCommand(String cmd) {
	String[] cmds = cmd.split(" ");
	String command = cmds[0];
	
	return commands.get(command);
    }
    
    protected String[] getArgs(String cmd) {
	String[] cmds = cmd.split(" ");
	
	return Arrays.copyOfRange(cmds, 1, cmds.length);
    }

    public HashMap<String, Command> getCommands() {
	return commands;
    }
}
